﻿
Imports System.IO
Imports std

'except for existing vector functions, also take care to transform from any to bytes, or bytes to any
'uses ToString and encoding.utf8.GetBytes, and encoding.utf8.GetString
'meanwhile, has export and import functions
'to export nettransData to bytes, and imports bytes from network to nettransData

Public Class nettransData
    Inherits vector(Of bytes)
    Implements IDisplay

    Public Const displayRange As UInt32 = 128

    Public Shared Function emptyInstance() As nettransData
        Static rtn As nettransData = New nettransData()
        rtn.size() = 0
        Return rtn
    End Function

    Public Function export(ByRef buff() As Byte, ByVal start As Int64, ByRef size As Int64) As Boolean
        Return serialize(buff, start, size,
                         Function(ByRef b As bytes, ByRef i As UInt64) As Boolean
                             If i >= Me.size() Then
                                 Return False
                             Else
                                 b = at(i)
                                 Return True
                             End If
                         End Function)
    End Function

    Public Function export(ByRef buff() As Byte, ByRef size As Int64) As Boolean
        Return export(buff, 0, size)
    End Function

    Public Function export(ByRef buff() As Byte) As Boolean
        Dim size As Int64 = 0
        Return export(buff, size)
    End Function

    Public Function import(ByVal buff() As Byte, ByVal start As Int64, ByVal size As Int64) As Boolean
        Return deserialize(buff, start, size,
                           Sub(ByRef i As Byte())
                               If Not empty() Then
                                   assert(object_compare(i, +(rbegin().get())) <> 0)
                               End If
                               assert(push_back(New bytes()))
                               rbegin().get().attach(i)
                           End Sub)
    End Function

    Public Function import(ByVal buff() As Byte) As Boolean
        If buff Is Nothing Then
            Return False
        End If
        Return import(buff, 0, buff.Length)
    End Function

    Public Function fieldCount() As Int64
        Return size()
    End Function

    Public Sub New()
        MyBase.New()
    End Sub

    Public Sub New(ByVal value As nettransData)
        MyBase.New()
        push_back(value.data)
    End Sub

    Public Function display(Optional ByVal length As Long = 64) As String Implements IDisplay.display
        Dim rtn As String = Nothing
        Dim i As Int64
        Dim buff As bytes = Nothing
        Dim temp As String = Nothing
        Dim singleRange As Int64
        If size() < 2 Then
            singleRange = displayRange
        Else
            singleRange = displayRange \ size()
        End If
        rtn = "{fieldCount}" + size().ToString
        For i = 0 To min(size() - 1, convertor.cast(Of Int64)(displayRange))
            buff = data(i)
            escape(System.Text.Encoding.UTF8.GetString(+buff, 0, min(buff.size, singleRange)), temp)
            rtn += character.fullStop
            rtn += character.fullStop
            rtn += character.fullStop
            rtn += character.sheffer
            rtn += character.leftBrace + buff.size.ToString + character.rightBrace + temp
        Next
        Return rtn
    End Function

    Public Overloads Function take(ByVal index As Int64) As bytes
        Dim rtn As bytes = Nothing
        If MyBase.take(index, rtn) Then
            Return rtn
        Else
            Return Nothing
        End If
    End Function

    Public Overloads Function take(ByVal index As Int64, ByRef value As bytes) As Boolean
        Return MyBase.take(index, value)
    End Function

    Public Overloads Function take(Of T)(ByVal index As Int64, ByRef value As T) As Boolean
        Dim field As bytes = Nothing
        field = take(index)
        If field Is Nothing Then
            value = Nothing
            Return False
        Else
            Dim str As String
            If Not +field Is Nothing Then
                str = encoding.utf8.GetString(+field, 0, field.size)
                Return convertor.cast(Of T)(str, value)
            Else
                Return False
            End If
        End If
    End Function

    Public Overloads Function take(Of valueT)(ByVal index As Int64) As valueT
        Dim temp As valueT
        If take(index, temp) Then
            Return temp
        Else
            Return Nothing
        End If
    End Function

    Public Overloads Function push_back(ByVal v As bytes) As Boolean
        Return MyBase.push_back(v)
    End Function

    Public Overloads Function push_back(ByVal v() As Byte) As Boolean
        Return MyBase.push_back(v)
    End Function

    Public Overloads Function push_back(Of valueT)(ByVal value As valueT) As Boolean
        Dim internal As bytes = New bytes(encoding.utf8.GetBytes(Convert.ToString(value)))
        Return MyBase.push_back(internal)
    End Function

    Public Overloads Function insert(ByVal v As bytes) As Boolean
        Return push_back(v)
    End Function

    Public Overloads Function insert(ByVal v() As Byte) As Boolean
        Return push_back(v)
    End Function

    Public Overloads Function insert(Of valueT)(ByVal value As valueT) As Boolean
        Return push_back(value)
    End Function

    Public Overrides Function Clone() As Object
        Dim rtn As nettransData = Nothing
        rtn = New nettransData(Me)

        Return rtn
    End Function

    Public Shared Sub unittest()
        Dim testsize As Int32 = 100000
        Dim d As nettransData = Nothing
        d = New nettransData
        Dim i As Int32
        perfCheckPoint(, "begin", True)
        For i = 0 To testsize
            d.insert("abc")
        Next
        perfCheckPoint(, "finish insert " + Convert.ToString(testsize + 1) + " 'abc' to d", True)
        Dim buff() As Byte = Nothing
        Dim size As Int32
        d.export(buff, size)
        perfCheckPoint(, "finish export from d", True)
        d.clear()
        perfCheckPoint(, "finish d.clear()", True)
        d.import(buff)
        perfCheckPoint(, "finish d.import(buff)", True)
        assert(testsize + 1 = d.fieldCount, "testsize+1<>d.fieldCount")
        For i = 0 To testsize
            assert(d.take(Of String)(i) = "abc", "d.take(Of String)(i) <> 'abc'")
        Next
        perfCheckPoint(, "finish d.take", True)
    End Sub
End Class
